package it.antonio.ilpizze.db.core;

import it.antonio.ilpizze.db.exceptions.BadStatusException;

public class StatusManager {
	
	private InnerStatusDelegate delegate;
	
	public StatusManager(Status status) {
		delegate = new SingleThreadDelegate(status);
	}
	
	public void multiThreading(boolean multiThreading) {
		if(multiThreading) {
			delegate = new MultiThreadDelegate(delegate.status());
		} else {
			delegate = new SingleThreadDelegate(delegate.status());	
		}
	}
	
	
	public void checkStatus(Status... expected) {
		for(Status e: expected){
			if(e == status()) return;
		}
		
		throw new BadStatusException(status(), expected);
	}

	public Status status() {
		return delegate.status();
	}
	
	public void status(Status status) {
		delegate.status(status);
	}
	
	
	
	private interface InnerStatusDelegate{
		Status status();
		void status(Status status);
	}
	
	private class SingleThreadDelegate implements InnerStatusDelegate{
		private Status status;
		
		public SingleThreadDelegate(Status status) {
			this.status = status;
		}

		public Status status() {
			return status;
		}

		public void status(Status status) {
			this.status = status;
		}
	}
	
	private class MultiThreadDelegate implements InnerStatusDelegate{
		private Status global;
		private ThreadLocal<Status> transactionStatus = new ThreadLocal<Status>();
		
		public MultiThreadDelegate(Status status) {
			if(status == Status.TRANSACTION) {
				transactionStatus.set(status);	
				global = Status.OPEN;
			} else {
				this.global = status;
			}
			
		}

		public Status status() {
			Status tx =transactionStatus.get(); 
			if(tx != null) return tx;
			return global;
		}

		public void status(Status status) {
			if(status == Status.TRANSACTION) {
				transactionStatus.set(status);	
			} else {
				transactionStatus.set(null);
				this.global = status;
			}
			
		}
		

	}

	
	
}
